package de.tum.control;

import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.xmlrpc.android.XMLRPCClient;
import org.xmlrpc.android.XMLRPCException;

import de.tum.datatypes.Exam;

import android.R.integer;
import android.database.CursorJoiner.Result;
import android.util.Log;

public class Synchronizer {

//	URI uri = URI.create("http://vmbaumgarten2.informatik.tu-muenchen.de/ExamOnlineApp/webservice/webservice.php");
	URI uri = URI.create("http://rupert.duerre.de/downloads/webservice.php");
	XMLRPCClient client = new XMLRPCClient(uri);
	
	
	public int checkLoginData(String username, String password) throws XMLRPCException{
		
		Map<String, String> credentials = new HashMap<String, String>();
		credentials.put("user", username);
		credentials.put("password", password);
		
		Map<String, Integer> result = (Map) client.call("demo.checkLogin", credentials);
		
		Log.d("Synchronizer","Login-Correct: "+result.get("userId"));
		
		return new Integer(result.get("userId"));
	}
	
	public List<Exam> getExams(int userId) throws XMLRPCException{
		
		List<Exam> examsOfId = new ArrayList<Exam>();
		
		Map<String, Integer> idResult = (Map) client.call("demo.getExamsToId", new Integer(userId));
		

		Log.d("Synchronizer - Get Exam Id","ResultSize is "+idResult.size());
		
		for(int i=0; i<idResult.size(); i++){
			Integer examId = idResult.get("Id-"+i);
			Log.d("Synchronizer - Get Exam Id","ID is "+examId.toString());
			
			Map<String, String> examResult = (Map) client.call("demo.examInformationToExamId", new Integer(examId));
			
			Exam newExam = new Exam();

			String subjectId = examResult.get("subjectId");
			if(subjectId.equals("-1") || subjectId.equals("-2") )
				break;
			
			String subjectName = examResult.get("subjectName");
			String examDateString = examResult.get("examDate");
			String evaluationBeginString = examResult.get("evaluationBegin");
			String evaluationEndString = examResult.get("evaluationEnd");
			
			Date examDate = stringToDate(examDateString);
			Date evaluationBeginDate = stringToDate(evaluationBeginString);
			Date evaluationEndDate = stringToDate(evaluationEndString);
						
			newExam.setId(examId);
			newExam.setSubjectName(subjectName);
			newExam.setSubjectIdentification(subjectId);
			newExam.setExamDate(examDate);
			newExam.setEvaluationBeginDate(evaluationBeginDate);
			newExam.setEvaluationEndDate(evaluationEndDate);
			newExam.setNumberOfParticipants(getNumberOfParticipants(examId));
			newExam.setNumberOfExercises(getNumberOfExercisesInExam(examId));
			
			
			examsOfId.add(newExam);
		}
		
		
		
//		int i=1;
//		Integer test = result.get("Id-"+i);
//		
//		Log.d("Synchronizer", test.toString());		
//		
		Log.d("Synchronizer", "Ending exam");		
//		
		return examsOfId;
	}
	
	public int getNumberExercisesFirstAndSecondCorrected(int examId) throws XMLRPCException{
		
		List<Integer> workedExams = workedExamsToExamId(examId);
		
		int nbrOfExercisesFirstcorrected = 0;
		int nbrOfExercisesSecondcorrected = 0;
		
		for(int workedExamId : workedExams){
			Map<String, Integer> credentials = new HashMap<String, Integer>();
			credentials.put("workedExamId", workedExamId);
			Map<String, Integer> result = (Map) client.call("demo.getNumberOfExercisesFirstCorrected", credentials);
			
			nbrOfExercisesFirstcorrected =  nbrOfExercisesFirstcorrected + new Integer(result.get("nbrOfExerciseFirstCorrected"));
			
			result = (Map) client.call("demo.getNumberOfExercisesSecondCorrected", credentials);
			
			nbrOfExercisesSecondcorrected =  nbrOfExercisesSecondcorrected + new Integer(result.get("nbrOfExerciseSecondCorrected"));
			
		}
		
		
		return nbrOfExercisesFirstcorrected+nbrOfExercisesSecondcorrected;
	}
	

	public int getExerciseType(int examId, int exerciseId) throws XMLRPCException{
		
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);
		credentials.put("exerciseId", exerciseId);
		
		Map<String, Integer> result = (Map) client.call("demo.getExerciseType", credentials);
		
		int exerciseType = new Integer(result.get("exerciseType"));
		
		return exerciseType;
	}
	
	public int getMaxPointsToExerciseType(int examId, int exerciseNumber) throws XMLRPCException{
		
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);
		credentials.put("exerciseId", exerciseNumber);
		
		Map<String, Integer> result = (Map) client.call("demo.getMaxPointsToExercise", credentials);
		
		int exerciseType = new Integer(result.get("maxPoints"));
		
		return exerciseType;
	}
	
		
	public int getMPChoiceExerciseId(int examId, int exerciseNumber, int exerciseType) throws XMLRPCException{
		
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);
		credentials.put("exerciseId", exerciseNumber);
		credentials.put("exerciseType", exerciseType);

		
		Map<String, Integer> result = (Map) client.call("demo.getMPChoiceExerciseId", credentials);
		
		int exerciseId = new Integer(result.get("exerciseId"));
		
			
		
		return exerciseId;
	}
	
	public List<Integer> getNbrAndIdOfMultipleChoiceQuestions(int exerciseId, int exerciseType) throws XMLRPCException{
		
		List<Integer> questionIds = new ArrayList<Integer>();
	
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("exerciseId", exerciseId);
		credentials.put("exerciseType", exerciseType);
		
		Map<String, Integer> result = (Map) client.call("demo.getNbrAndIdOfMultipleChoiceQuestions", credentials);
		
		Integer nbrOfQuestion = new Integer(result.get("nbrOfMPChoiceQuestions"));
		
		Log.d("Sync", "Nbr Of Questions: "+nbrOfQuestion);
		
		for(int i=0; i<nbrOfQuestion; i++){
			Integer mpQuestionId = result.get("Id-"+i);
			Log.d("Synchronizer - Get mpQuestionId Id","ID is "+mpQuestionId.toString());
			questionIds.add(mpQuestionId);
		}
		return questionIds;
	}
	
	
	public List<boolean[]> getSolutionArrayToMPQuestions(List<Integer> questionIds, int exerciseType) throws XMLRPCException {
		
		List<boolean[]> correctArrays = new ArrayList<boolean[]>();
		
		for(Integer questionId : questionIds){
			Map<String, Integer> credentials = new HashMap<String, Integer>();
			credentials.put("questionId", questionId);
			credentials.put("exerciseType", exerciseType);
			
			Map<String, Integer> result = (Map) client.call("demo.getSolutionIndexesToMPQuestion", credentials);
			
			Integer nbrOfAnswerPossibilities = new Integer(result.get("nbrOfAnswerPossibilites"));
			
			Integer nbrOfCorrectAnswerPossibilities = new Integer(result.get("nbrOfCorrectAnswerPossibilites"));
						
			Log.d("Sync", "Nbr Of Answer possibilites: "+nbrOfAnswerPossibilities);
			
			Log.d("Sync", "Nbr Of Answer possibilites: "+nbrOfCorrectAnswerPossibilities);
			
			boolean[] curBool = new boolean[nbrOfAnswerPossibilities];
			
			
			for(int i=0; i<nbrOfCorrectAnswerPossibilities; i++){
				Integer solutionIndex = result.get("Index-"+i);
				Log.d("Synchronizer - Get AnswerPossibilities ", "Correct Answer possibilites "+solutionIndex.toString());
				curBool[solutionIndex] = true;
			}
			
			correctArrays.add(curBool);
			
		}
		
		return correctArrays;
	}
	
public double getPointsPerSelectionMPChoiceQuestion(int exerciseId, int exerciseType) throws XMLRPCException {
		
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("exerciseId", exerciseId);
		credentials.put("exerciseType", exerciseType);
		
		Map<String, Double> result = (Map) client.call("demo.getPointsPerSelection", credentials);
		
		Double pointsPerSelection = result.get("pointsPerSelection");
		Log.d("Synchronizer", "pointsPerSelection "+pointsPerSelection);
		
		
		return pointsPerSelection;
	}
	
	public boolean sendExerciseToServer(int examId, String studentsName, String studentsMatrNr, int correctionState, int exerciseNumber, double archievedPoints) throws XMLRPCException {
		
		int workedExamId = getWorkedExamToExamIdAndMatrNr(examId, studentsMatrNr);
		Log.d("Synchronizer", "Id of worked Exams: "+workedExamId);
		
		boolean workedExamAlreadyExists = false;
		if(workedExamId == -1){
			workedExamAlreadyExists = false;
		}else{
			workedExamAlreadyExists = true;
		}
		
		if(!workedExamAlreadyExists){
			Map<String, String> credentials = new HashMap<String, String>();
			credentials.put("examId", ""+examId);
			credentials.put("studentsMatrNr", studentsMatrNr);
			credentials.put("studentsName", studentsName);
			credentials.put("correctionState", ""+correctionState);
			credentials.put("exerciseNumber", ""+exerciseNumber);
			credentials.put("archievedPoints", ""+archievedPoints);
			
			Map<String, Integer> result = (Map) client.call("demo.insertWorkedExamAndExerciseResult", credentials);
			Integer id = result.get("workedExamId"); 

			workedExamId = id;
			
			Log.d("Synchronizer", "inserted worked exam: "+workedExamId);
			
		}else{
			Map<String, String> credentials = new HashMap<String, String>();
			credentials.put("workedExamId", ""+workedExamId);
			credentials.put("examId", ""+examId);
			credentials.put("studentsMatrNr", studentsMatrNr);
			credentials.put("studentsName", studentsName);
			credentials.put("correctionState", ""+correctionState);
			credentials.put("exerciseNumber", ""+exerciseNumber);
			credentials.put("archievedPoints", ""+archievedPoints);
			
			Map<String, Boolean> result = (Map) client.call("demo.updateWorkedExamAndExerciseResult", credentials);
			Boolean correct = result.get("correct"); 

			Log.d("Synchronizer", "updated worked exam:  "+workedExamId);
						
		}
		
		
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("workedExamId", workedExamId);
		
		Map<String, Double> result = (Map) client.call("demo.getAchievedPointsFirstCorrection", credentials);

		Double achievedPoints = new Double(result.get("achievedPoints"));

		Log.d("Synchronizer", "updated worked exam - achieved points:  "+achievedPoints);
		
		Map<String, Double> getGradeCredentials = new HashMap<String, Double>();
		getGradeCredentials.put("examId", (double) examId);
		getGradeCredentials.put("achievedPoints", achievedPoints);
		getGradeCredentials.put("workedExamId", (double) workedExamId);
		
		Map<String, Double> resultGetGrade = (Map) client.call("demo.getGradeToAchievedPoints", getGradeCredentials);

		Double grade = new Double(resultGetGrade.get("grade"));
		
		Log.d("Synchronizer", "updated worked exam - achieved grade:  "+grade);
		
		return true;
	}
	
	public int getWorkedExamToExamIdAndMatrNr(int examId, String studentsMatrNr) throws XMLRPCException{
		
		Map<String, String> credentials = new HashMap<String, String>();
		credentials.put("examId", ""+examId);
		credentials.put("studentsMatrNr", studentsMatrNr);
		
		Map<String, Integer> result = (Map) client.call("demo.workedExamToExamIdWithMatrNrExists", credentials);
		
		Integer workedExamId = new Integer(result.get("workedExamId"));
		return workedExamId;
	}
	
	
	
	public List<Integer> workedExamsToExamId(int examId) throws XMLRPCException{
		
		List<Integer> workedExams = new ArrayList<Integer>();

		Log.d("Synchronizer", "workedExam examId: "+examId);
		
		
		Map<String, Integer> result = (Map) client.call("demo.workedExamsToExamId", examId);
		
		Integer nbrOfWorkedExams = new Integer(result.get("size"));
		Log.d("Synchronizer", "workedExam size: "+nbrOfWorkedExams);
		
		for(int i=0; i<nbrOfWorkedExams; i++){
			Integer workedExamId = result.get("Id-"+i);
			Log.d("Synchronizer - Worked Exams ", "worked exam id: "+workedExamId.toString());
			workedExams.add(workedExamId);
		}
		
		return workedExams;
	}
	
	public int getNumberOfParticipants(int examId) throws XMLRPCException{
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);

		Map<String, Integer> result = (Map) client.call("demo.getNumberOfParticipants", credentials);

		Integer nbrOfParticipants = new Integer(result.get("nbrOfParticipants"));
		
		return nbrOfParticipants;
	}
	
	public int getNumberOfFailed(int examId) throws XMLRPCException{
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);

		Map<String, Integer> result = (Map) client.call("demo.getNumberOfFailed", credentials);

		Integer nbrOfFailed = new Integer(result.get("nbrOfFailed"));
		
		return nbrOfFailed;
	}
	
	public int getNumberOfPassed(int examId) throws XMLRPCException{
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);

		Map<String, Integer> result = (Map) client.call("demo.getNumberOfPassed", credentials);

		Integer nbrOfPassed = new Integer(result.get("nbrOfPassed"));
		
		return nbrOfPassed;
	}
	
	public double getAverageGrade(int examId) throws XMLRPCException{
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);

		Map<String, Double> result = (Map) client.call("demo.getAverageGrade", credentials);

		Double average = new Double(result.get("average"));
		
		return average;
	}

	public double getAverageGradeOfPassed(int examId) throws XMLRPCException{
		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);

		Map<String, Double> result = (Map) client.call("demo.getAverageGradeOfPassed", credentials);

		Double average = new Double(result.get("average"));
		
		return average;
	}
	
	public List<Double> getListOfAchievedPointsFirstCorrection(int examId) throws XMLRPCException{

		List<Integer> workedExams = workedExamsToExamId(examId);
		
		List<Double> achievedPointsList = new ArrayList<Double>();
		
		for(Integer workedExamId : workedExams){
			Map<String, Integer> credentials = new HashMap<String, Integer>();
			credentials.put("workedExamId", workedExamId);
			

			Map<String, Double> result = (Map) client.call("demo.getAchievedPointsFirstCorrection", credentials);

			Double achievedPoints = new Double(result.get("achievedPoints"));

			achievedPointsList.add(achievedPoints);
			
		}
		
		return achievedPointsList;
	}
	
	public int getMaxPointsInExam(int examId) throws XMLRPCException{

		int maxPoints = 0;
		
		for(int exerciseNumber=1; exerciseNumber<=getNumberOfExercisesInExam(examId); exerciseNumber++){
			maxPoints = maxPoints + getMaxPointsToExerciseType(examId, exerciseNumber);
		}
		
		return maxPoints;
	}
	
	public double[] getMaxPointsPerExercise(int examId) throws XMLRPCException{

		int nbrOfExercisesInExam = getNumberOfExercisesInExam(examId);
		
		double[] maxPointsPerExercise = new double[nbrOfExercisesInExam];
		
		for(int exerciseNumber=0; exerciseNumber<getNumberOfExercisesInExam(examId); exerciseNumber++){
			maxPointsPerExercise[exerciseNumber] = (double) getMaxPointsToExerciseType(examId, exerciseNumber+1);
		}
		
		return maxPointsPerExercise;
	}
	
	public double[] getAveragePointsPerExercise(int examId) throws XMLRPCException{
		
		List<Integer> workedExams = workedExamsToExamId(examId);

		int nbrOfExercisesInExam = getNumberOfExercisesInExam(examId);
		
		Log.d("Sychronizer", "AveragePoints - nbrOfExercisesInExam "+nbrOfExercisesInExam);
		
		double[] averagePointsPerExercise = new double[nbrOfExercisesInExam];
		
		for(int exerciseNumber=0; exerciseNumber<nbrOfExercisesInExam; exerciseNumber++){
			Map<String, Integer> credentials = new HashMap<String, Integer>();
			credentials.put("exerciseNumber", exerciseNumber+1);
			Log.d("Sychronizer", "AveragePoints - exerciseNumber "+(exerciseNumber+1));
			credentials.put("nbrOfWorkedExams", workedExams.size());
			Log.d("Sychronizer", "AveragePoints - workedExams "+workedExams.size());
			for(int i=0; i<workedExams.size(); i++){
				credentials.put("workedExamId"+i, workedExams.get(i));
			}
			
			Map<String, Double> result = (Map) client.call("demo.getAveragePointsForExeciseInExam", credentials);

			averagePointsPerExercise[exerciseNumber] = (double) result.get("averagePoints");
			Log.d("Sychronizer", "AveragePoints - averagePoints "+averagePointsPerExercise[exerciseNumber]);
			
		}
		
		return averagePointsPerExercise;
	}
	
	public int getNumberOfExercisesInExam(int examId) throws XMLRPCException{

		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);
		
		Map<String, Integer> result = (Map) client.call("demo.getNumberOfExercises", credentials);
		
		Integer nbrOfExercises = result.get("count");
		
		return nbrOfExercises;
	}
	
	public int[] getGradingDistributionArray(int examId) throws XMLRPCException{

		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("examId", examId);
		
		Map<String, Integer> result = (Map) client.call("demo.getGradingDistributionArray", credentials);
		
		int[] gradingDistributionArray = new int[]{
				(int)result.get("1.0"),(int)result.get("1.3"),(int)result.get("1.7"),
				(int)result.get("2.0"),(int)result.get("2.3"),(int)result.get("2.7"),
				(int)result.get("3.0"),(int)result.get("3.3"),(int)result.get("3.7"),
				(int)result.get("4.0"),(int)result.get("4.3"),(int)result.get("4.7"),
				(int)result.get("5.0")};
		
		return gradingDistributionArray;
	}
	
	public List<Integer> getFirstCorrectedExams(int workedExamId) throws XMLRPCException{

		Map<String, Integer> credentials = new HashMap<String, Integer>();
		credentials.put("workedExamId", workedExamId);
		
		Map<String, Integer> result = (Map) client.call("demo.getFirstCorrectedExercisesToWorkedExam", credentials);
		
		Integer size = result.get("size");
		
		Log.d("Synchronizer", "first corrections size: "+size);
		
		List<Integer> firstCorrectedExams = new ArrayList<Integer>();
		
		for(int i=0; i<size; i++){
			Integer curCounter = result.get("Counter-"+i);
			firstCorrectedExams.add(curCounter);
		}
		
		
		return firstCorrectedExams;
	}

	
	public boolean addOrUpdateSecondCorrection(int workedExamId, int exerciseNumber, double achievedPoints) throws XMLRPCException{

		Map<String, Object> credentials = new HashMap<String, Object>();
		credentials.put("workedExamId", workedExamId);
		credentials.put("exerciseNumber", exerciseNumber);
		credentials.put("achievedPoints", achievedPoints);
		
		Map<String, Boolean> result = (Map) client.call("demo.insertOrUpdateSecondCorrection", credentials);
		
		Boolean correct = (Boolean) result.get("result");
		
		Log.d("Synchronizer", "result: "+correct);
		
		return correct;
	}

	
	/************************************************************************************************
	 * HELPER METHODS
	 ***********************************************************************************************/
	
	/**
	 * 
	 * 
	 * @param timeStampString
	 * @return
	 */
	private Date stringToDate(String timeStampString){
		Log.d("TimeStamp", ""+timeStampString);
		
		String[] dateTypes = timeStampString.split(" ");
		Log.d("dateTypes Size", ""+dateTypes.length);
		
		String dateString = dateTypes[0];
		Log.d("DateString", ""+dateString);
		String[] dateParameters = dateString.split("-");
		Log.d("dateParameters Size", ""+dateParameters.length);
		String dayString = dateParameters[2];
		String monthString = dateParameters[1];
		String yearString = dateParameters[0];
		
		int day = new Integer(dayString);
		int month = new Integer(monthString);
		int year = new Integer(yearString);
		
		String timeString = dateTypes[1];
		Log.d("timeString", ""+timeString);
		String[] timeParameters = timeString.split(":");
		String hourString = timeParameters[0];
		String minuteString = timeParameters[1];
		
		int hour = new Integer(hourString);
		int minute = new Integer(minuteString);
		
		Date date = new Date(year-1900, month-1, day, hour, minute);
		
		return date;
	}

	
	
}
